package com.dave.admin.modular.boss.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dave.admin.common.exception.AssertionEx;
import com.dave.admin.modular.boss.dto.MenuNode;
import com.dave.admin.modular.boss.dto.PermissionNode;
import com.dave.admin.modular.boss.dto.PermissionVo;
import com.dave.admin.modular.boss.entity.Permission;
import com.dave.admin.modular.boss.mapper.PermissionMapper;
import com.dave.admin.util.SecurityUtil;
import com.dave.admin.modular.boss.service.IPermissionService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限表 服务实现类
 * </p>
 *
 * @author Dave
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {


    @Override
    public List<PermissionNode> treeList() {
        return treeList(new QueryWrapper());
    }

    /**
     * 需要和前端的路由对应：有规律的
     */
    private static final Map crud = MapUtil.newHashMap(4);

    static {
        crud.put("Add", "新增");
        crud.put("Detail", "详情");
        crud.put("Update", "修改");
        crud.put("Delete", "删除");
    }


    @Override
    public List<PermissionNode> treeList(QueryWrapper queryWrapper) {
        List<Permission> permissionList = this.list(queryWrapper);
        List<PermissionNode> result = permissionList.stream().filter(permission -> permission.getParentId().equals("0"))
                .map(permission -> covert(permission, permissionList)).collect(Collectors.toList());
        return result;
    }


    /**
     * 获取当前用户信息的所有权限
     */
    @Override
    public List<Permission> permissionList(String userAdminId) {
        return super.baseMapper.getPermissionList(userAdminId);
    }

    /**
     * 获取当前用户的菜单节点
     */
    @Override
    public List<MenuNode> menuList() {
        //菜单不包括按钮
        List<Permission> permissionList = SecurityUtil.getPermissionList()
                .stream().filter(permission -> permission.getType() != Permission.TYPE_BUTTON)
                .collect(Collectors.toList());

        List<MenuNode> result = permissionList.stream()
                .filter(permission -> permission.getParentId().equals("0"))
                .map(permission -> covertMenuNode(permission, permissionList)).collect(Collectors.toList());
        return result;
    }


    /**
     * 按钮下不能挂载节点
     */
    @Override
    public List<Map> parentList(String name) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.ne(Permission.TYPE, Permission.TYPE_BUTTON);
        queryWrapper.like(Permission.NAME, Optional.ofNullable(name).orElse(""));
        List<Map> listMaps = this.listMaps(queryWrapper.select(Permission.NAME, Permission.ID));
        listMaps.add(0, MapUtil.builder()
                .put(Permission.NAME, "无")
                .put(Permission.ID, "0")
                .build());
        return listMaps;
    }

    @Override
    public void beforeAdd(Permission entity, PermissionVo permissionVo) {
        AssertionEx.isFalse(!entity.getType().equals(Permission.TYPE_MENU) && permissionVo.isCreateChildButton(), "菜单才能创建子按钮权限");
        AssertionEx.isFalse(entity.getParentId().equals("0") && entity.getType().equals(Permission.TYPE_BUTTON), "无不能创建按钮");
        //不是顶级菜单的情况
        if (!entity.getParentId().equals("0")) {
            Permission parentPermission = this.getById(entity.getParentId());
            AssertionEx.notNull(parentPermission, "父权限没有找到数据");
            AssertionEx.isFalse(parentPermission.getType().equals(Permission.TYPE_DIRECTORY) && entity.getType().equals(Permission.TYPE_BUTTON), "目录不能创建按钮");
            AssertionEx.isFalse(parentPermission.getType().equals(Permission.TYPE_BUTTON) && entity.getType().equals(Permission.TYPE_BUTTON), "按钮不能创建按钮");
            AssertionEx.isFalse(parentPermission.getType().equals(Permission.TYPE_MENU) && entity.getType().equals(Permission.TYPE_DIRECTORY), "菜单不能创建目录");
        }
    }

    /**
     * 保存当前对象的同时【创建子button权限：  新增  详情 修改 删除】
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doSave(Permission entity) {
        this.save(entity);
        List<Permission> permissionList = new ArrayList<>();
        crud.keySet().stream().forEach(x -> {
            Permission permission = new Permission();
            permission.setName(entity.getName() + "-" + crud.get(x));
            permission.setValue(entity.getValue() + "-" + x);
            permission.setParentId(entity.getId());
            permission.setType(Permission.TYPE_BUTTON);
            permission.setDescription(permission.getName());
            permissionList.add(permission);
        });
        this.saveBatch(permissionList);
        return true;
    }

    @Override
    public void afterGetItem(Permission entity) {
        if (entity.getParentId().equals("0")) {
            entity.setParentName("无");
        } else {
            Permission permission = this.getById(entity.getParentId());
            permission = Optional.ofNullable(permission).orElse(new Permission());
            entity.setParentName(permission.getName());
        }
    }


    @Override
    public void beforeDelete(String id) {
        Permission permission = this.getById(id);
        AssertionEx.notNull(permission, "该权限没有找到");
        long hasChildPer = this.count(new QueryWrapper<Permission>().eq(Permission.PARENT_ID, permission.getId()));
        AssertionEx.isTrue(hasChildPer == 0, "该权限挂载子节点，无法直接删除");
    }

    /**
     * 将权限转换为带有子级的权限对象
     * 当找不到子级权限的时候map操作不会再递归调用covert
     */
    private PermissionNode covert(Permission permission, List<Permission> permissionList) {
        PermissionNode node = new PermissionNode();
        BeanUtils.copyProperties(permission, node);
        List<PermissionNode> children = permissionList.stream()
                .filter(subPermission -> subPermission.getParentId().equals(permission.getId()))
                .map(subPermission -> covert(subPermission, permissionList)).collect(Collectors.toList());
        node.setChildren(children);
        return node;
    }

    /**
     * 转换成前端菜单的节点
     */
    private MenuNode covertMenuNode(Permission permission, List<Permission> permissionList) {
        MenuNode node = new MenuNode();
        node.setIcon(permission.getIcon());
        node.setTitle(permission.getName());
        node.setKey(permission.getValue());
        List<MenuNode> children = permissionList.stream()
                .filter(subPermission -> subPermission.getParentId().equals(permission.getId()))
                .map(subPermission -> covertMenuNode(subPermission, permissionList)).collect(Collectors.toList());
        node.setChildren(children);
        return node;
    }


    @Override
    public void save(PermissionVo permissionVo) {
        Permission permission = BeanUtil.toBean(permissionVo, Permission.class);
        this.beforeAdd(permission, permissionVo);
        //需要创建子权限：  新增  详情 修改 删除
        if (permissionVo.isCreateChildButton()) {
            this.doSave(permission);
        } else {
            this.save(permission);
        }
    }
}
